module divider(

 iClk, 	 	 // input clock

 iReset, 	 	 // reset signal

 iReady, 	 	 // indicates inputs are ready

 oDone, 	 	 // indicates that the result is ready

 iDividend, 	 	 // 16-bit multiplier [15:0]

 iDivisor, 	 	 // 8-bit multiplicand [7:0]

 oQuotient, 		 // 8-bit quotient [7:0]

	 oReminder 	 // 8-bit reminder [7:0]

 );



	input iClk; 	 	 // input clock

	input iReset; 	 	 // reset signal

	input iReady; 	 	 // indicates inputs are ready

	output oDone; 	 	 // indicates that the result is ready

	input [15:0] iDividend; 	 	 // 16-bit multiplier [15:0]

	input [7:0] iDivisor; 	 	 // 8-bit multiplicand [7:0]

	output [7:0] oQuotient; 		 // 8-bit quotient [7:0]

	output [7:0] oReminder; 	 // 8-bit reminder [7:0]

	//used between FFs. (in combinational circuit)
	 wire [7:0] Aout[8:0], Qout[8:0];
	 wire [7:0] M;
	 wire [7:0] QuotientResult;
	 wire [7:0] ReminderResult;
	 
	 wire prevready, haddone; //to control oDone signal
	 
	 genvar i;
	 
	 //duplicate same circuit by 8 times
	 generate
		 for(i=7;i>=0;i=i-1)
		 begin: DFFs8bit
			//registers to give combinational circuit appropriate value, or to save the result
			DFF RDividendFront( .D(iDividend[i+8]), .C(iClk), .Q(Aout[8][i]), .RESET(iReset) );
			DFF RDividendRear( .D(iDividend[i]), .C(iClk), .Q(Qout[8][i]), .RESET(iReset) );
			DFF RM( .D(iDivisor[i]), .C(iClk), .Q(M[i]), .RESET(iReset) );
			DFF RQoutient( .D(QuotientResult[i]), .C(iClk), .Q(oQuotient[i]), .RESET(iReset) );
			DFF RReminder( .D(ReminderResult[i]), .C(iClk), .Q(oReminder[i]), .RESET(iReset) );
			
		 end
	 endgenerate
	 
	 //registers to control oDone signal
	 DFF RReady( .D(iReady), .C(iClk), .Q(prevready), .RESET(iReset) );
	 DFF RHadDone( .D(oDone|haddone), .C(iClk), .Q(haddone), .RESET(iReset) );
	 DFF RDone( .D(prevready|(~iReady&haddone)), .C(iClk), .Q(oDone), .RESET(iReset) );
	 

	 
	 
	 generate
		 for(i=7;i>=0;i=i-1)
		 begin: manydigits
		 //calculate bit by bit * 8 times
			divider1bitoperator onebit(Aout[i+1], Qout[i+1], M, Aout[i], Qout[i]);
			
		 end
	 endgenerate
	 
	 //save the result of the entire process
	 assign ReminderResult=Aout[0];
	 ALU aluQ_2sComp(8'b0, Qout[0], Aout[8][7]^M[7], QuotientResult, );
	 
	 
 endmodule
 
 
 //divider bit-by-bit caculator
 module divider1bitoperator(Ain, Qin, M, Aout, Qout);
				input [7:0] Ain, Qin, M;
				output [7:0] Aout, Qout;
			
				wire [7:0] A, Q;
				wire areAandMSamesigned;
				wire [7:0] ALUPassedA;
				wire isALUPassedA_0, isASameasBefore, isQ0_1;
				
				
				 //shift
				 assign A={Ain[6:0], Qin[7]};
				 assign Q={Qin[6:0], 1'b0};
				 
				 //sign comparision between A and M
				 assign areAandMSamesigned=A[7]~^M[7];
				 
				 //subtract
				 ALU aluAMsub(A, M, areAandMSamesigned, ALUPassedA, );
				 
				 //sign comparision between ALUPassedA and A(original), or check if ALUPassedA==0
				 assign isASameasBefore=A[7]~^ALUPassedA[7];
				 assign isALUPassedA_0=~|ALUPassedA;
				 assign isQ0_1=isASameasBefore|isALUPassedA_0;
				 
				 //save the result
				 assign Aout=( ALUPassedA & {8{isQ0_1}} ) | ( A & {8{~isQ0_1}} ); //structure of mux
				 assign Qout= { Q[7:1], ( 1'b1 & isQ0_1 ) | ( 1'b0 & ~isQ0_1 ) };
			 endmodule
 
//////////////////////////////////////////////////////////////////////////////////
//				sub module					//
//////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////
// 		Half Adder 		//////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
module HA(A,B,S,Cout);

input A,B;
output S,Cout;

	xor(S,A,B);
	and(Cout,A,B);

endmodule

//////////////////////////////////////////////////////////////////////////////////
// 		Full Adder 		//////////////////////////////////////////	
//////////////////////////////////////////////////////////////////////////////////
module FA(A,B,Cin,S,Cout);

input A,B,Cin;
output S,Cout;

wire w1, w2, w3;

	HA ha0(A,B,w1,w2);
	HA ha1(w1,Cin,S,w3);
	or(Cout,w2,w3);

endmodule


//////////////////////////////////////////////////////////////////////////////////
// 	8 bit Ripple Carry Adder	//////////////////////////////////////////	
//////////////////////////////////////////////////////////////////////////////////
module RCA(A,B,C0,S,C8);

input [7:0]A;
input [7:0]B;
input C0;
output [7:0]S;
output C8;

wire C1,C2,C3,C4,C5,C6,C7;

	FA fa0(A[0],B[0],C0,S[0],C1); //mod start
	FA fa1(A[1],B[1],C1,S[1],C2);
	FA fa2(A[2],B[2],C2,S[2],C3);
	FA fa3(A[3],B[3],C3,S[3],C4);
	FA fa4(A[4],B[4],C4,S[4],C5);
	FA fa5(A[5],B[5],C5,S[5],C6);
	FA fa6(A[6],B[6],C6,S[6],C7);
	FA fa7(A[7],B[7],C7,S[7],C8); //mod end

endmodule

//////////////////////////////////////////////////////////////////////////////////
// 	8 bit Adder and Subtracto	//////////////////////////////////////////	
//////////////////////////////////////////////////////////////////////////////////
module ALU(A,B,C0,S,C8);

input [7:0]A;
input [7:0]B;
input C0;
output [7:0]S;
output C8;

wire [7:0]N;

	xor(N[0],B[0],C0);
	xor(N[1],B[1],C0);
	xor(N[2],B[2],C0);
	xor(N[3],B[3],C0);
	xor(N[4],B[4],C0);
	xor(N[5],B[5],C0);
	xor(N[6],B[6],C0);
	xor(N[7],B[7],C0);

	RCA rca0(A,N,C0,S,C8);

endmodule

//////////////////////////////////////////////////////////////////////////////////
// 	     8 to 1 Multiplexer		//////////////////////////////////////////	
//////////////////////////////////////////////////////////////////////////////////
module MUX8(I7,I6,I5,I4,I3,I2,I1,I0,S2,S1,S0,O);

input I7,I6,I5,I4,I3,I2,I1,I0;
input S2,S1,S0;
output O;

wire n0, n1, n2, r0, r1, r2, r3, r4, r5, r6, r7;

	not(n0,S0);
	not(n1,S1);
	not(n2,S2);
	and(r0,n0,n1,n2,I0);
	and(r1,S0,n1,n2,I1);
	and(r2,n0,S1,n2,I2);
	and(r3,S0,S1,n2,I3);
	and(r4,n0,n1,S2,I4);
	and(r5,S0,n1,S2,I5);
	and(r6,n0,S1,S2,I6);
	and(r7,S0,S1,S2,I7);
	or(O,r0,r1,r2,r3,r4,r5,r6,r7);

endmodule


//////////////////////////////////////////////////////////////////////////////////
// 	     4 to 1 Multiplexer		//////////////////////////////////////////	
//////////////////////////////////////////////////////////////////////////////////
module MUX4(I3,I2,I1,I0,S1,S0,O);

input I3,I2,I1,I0;
input S1,S0;
output O;

wire n0, n1, r0, r1, r2, r3;

	not(n0,S0);
	not(n1,S1);
	and(r0,n0,n1,I0);
	and(r1,S0,n1,I1);
	and(r2,n0,S1,I2);
	and(r3,S0,S1,I3);
	or(O,r0,r1,r2,r3);

endmodule

//////////////////////////////////////////////////////////////////////////////////
// 		D FlipFlop 		//////////////////////////////////////////	
//////////////////////////////////////////////////////////////////////////////////
module DFF(D,C,Q,RESET);

input D, C,RESET;
output Q;
reg Q;
	
	always @ (posedge RESET or posedge C)
	begin
		if(RESET)
			Q <= 1'b0;
		else
			Q <= D;
	end
	
endmodule